package com.jiazaibendi.lottery.config;

import com.jiazaibendi.lottery.common.CommonConstant;
import com.jiazaibendi.lottery.dao.domain.Prize;
import com.jiazaibendi.lottery.dao.domain.PrizeExample;
import com.jiazaibendi.lottery.dao.domain.Scheme;
import com.jiazaibendi.lottery.dao.domain.SchemeExample;
import com.jiazaibendi.lottery.dao.mapper.PrizeMapper;
import com.jiazaibendi.lottery.dao.mapper.SchemeMapper;
import com.jiazaibendi.lottery.service.PrizePoolService;
import com.jiazaibendi.lottery.service.RecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

/**
 * description
 * 定时器
 * @author echo_kai
 * @version 1.0
 * @date 2021/08/07
 */
@Configuration
@EnableScheduling
public class StaticScheduleTaskConfig {

    @Autowired
    private SchemeMapper schemeMapper;

    @Autowired
    private PrizeMapper prizeMapper;

    @Autowired
    private RecordService recordService;

    @Autowired
    private PrizePoolService prizePoolService;

    @PostConstruct
    public void init() {
        SchemeExample example = new SchemeExample();
        example.createCriteria().andStartTimeLessThanOrEqualTo(new Date()).andEndTimeGreaterThan(new Date());
        List<Scheme> schemeList = schemeMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(schemeList)) return;
        schemeList.forEach(scheme -> {
            prizePoolService.clearPrizePool(scheme.getId());

        });
        updatePrizePool();
    }

    @Scheduled(cron = "0 0 * * * ?")
    private void updatePrizePool() {
        SchemeExample example = new SchemeExample();
        example.createCriteria().andStartTimeLessThanOrEqualTo(new Date()).andEndTimeGreaterThan(new Date());
        List<Scheme> schemeList = schemeMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(schemeList)) return;
        schemeList.forEach(scheme ->{
            PrizeExample prizeExample = new PrizeExample();
            prizeExample.createCriteria().andSchemeIdEqualTo(scheme.getId());
            List<Prize> prizeList = prizeMapper.selectByExample(prizeExample);
            List<Long> allPrize = prizePoolService.queryAllPrizeOfPrizePool(scheme.getId());
            addPrizeToPool(prizeList, scheme, allPrize);
            recordService.clearHourFlow(scheme.getId());
        });
    }

    private void addPrizeToPool(List<Prize> prizeList, Scheme scheme, List<Long> allPrizeList) {
        List<Long> resultList = new ArrayList<>();
        long curTime = new Date().getTime();
        long curHMSTime = (curTime - CommonConstant.DAY_DIFF_MILLIS_SECONDS) % CommonConstant.DAY_MILLIS_SECONDS;
        String today = Long.toString((curTime - scheme.getStartTime().getTime()) / CommonConstant.DAY_MILLIS_SECONDS + 1);
        prizeList.forEach(prize -> {
            List<String> days = Arrays.asList(prize.getDay().split(","));
            long startTime = (prize.getDayStartTime().getTime() - CommonConstant.DAY_DIFF_MILLIS_SECONDS) % CommonConstant.DAY_MILLIS_SECONDS;
            long endTime = (prize.getDayEndTime().getTime() - CommonConstant.DAY_DIFF_MILLIS_SECONDS) % CommonConstant.DAY_MILLIS_SECONDS;
            if (curHMSTime >= startTime
                   && curHMSTime < endTime
                   && prize.getRemaining() - prize.getCountPerHour() >= 0
                   && days.contains(today)) {
               prize.setRemaining(prize.getRemaining() - prize.getCountPerHour());
               prizeMapper.updateByPrimaryKey(prize);
               IntStream.range(0, prize.getCountPerHour()).forEach(i -> resultList.add(prize.getId()));
           }
        });
        long lastHourFlow = recordService.queryHourFlow(scheme.getId());
        lastHourFlow = Math.max(lastHourFlow, CommonConstant.PRIZE_POOL_BASE_SIZE);
        allPrizeList.addAll(resultList);
        if (lastHourFlow >= allPrizeList.size()) LongStream.range(0, lastHourFlow - allPrizeList.size()).forEach(num -> allPrizeList.add(0L));
        Collections.shuffle(allPrizeList);
        prizePoolService.clearPrizePool(scheme.getId());
        prizePoolService.addPrizeToPrizePool(scheme.getId(), allPrizeList);
    }
}
